#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <sys/wait.h>
#include <functional>
#include "log.hpp"
#include "inetaddr.hpp"
#include "dict.hpp"
using namespace hllog;
using namespace hladdr;
using func_t = std::function<std::string(std::string)>;
class TcpServer
{
    void Server(int rwfd)
    {
        while (true)
        {
            char buff[256];
            int rn = read(rwfd, buff, sizeof(buff) - 1);
            if (rn < 0)
            {
                // read出错
                LOG(Level::ERROR) << "read error";
                break;
            }
            else if (rn == 0)
            {
                // write端退出
                LOG(Level::INFO) << "writer is exit";
                break;
            }
            // 读取成功
            buff[rn] = '\0';
            std::cout << "read : " << buff << std::endl;
            // 发送信息, 这里简单将信息发送回去
            int wn = write(rwfd, buff, rn);
            if (wn < 0)
            {
                LOG(Level::ERROR) << "write error";
                break;
            }
        }
    }
    void Server(int rwfd, InetAddr &addr)
    {
        while (true)
        {
            char english[256];
            int rn = read(rwfd, english, sizeof(english) - 1);
            if (rn < 0)
            {
                // read出错
                LOG(Level::ERROR) << "read error";
                break;
            }
            else if (rn == 0)
            {
                // write端退出
                LOG(Level::INFO) << "writer is exit";
                break;
            }
            // 读取成功
            english[rn] = '\0';
            std::string chinese = _func(english);
            std::cout << addr.ToString() << " : " << english << " -> " << chinese << std::endl;
            int wn = write(rwfd, chinese.c_str(), chinese.size());
            if (wn < 0)
            {
                LOG(Level::ERROR) << "write error";
                break;
            }
        }
    }

public:
    TcpServer(uint16_t port, func_t func) : _sockfd(-1), _port(port), _func(func)
    {
    }
    ~TcpServer() {}
    void Init()
    {
        // 1. socket
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            LOG(Level::FATAL) << "socket error";
            exit(1);
        }
        LOG(Level::DEBUG) << "socket success";
        // 2. bind
        InetAddr addr(_port);
        int b = bind(_sockfd, addr.GetInetAddr(), addr.GetLen());
        if (b < 0)
        {
            LOG(Level::FATAL) << "bind error";
            exit(2);
        }
        LOG(Level::DEBUG) << "bind success";
        int l = listen(_sockfd, 5);
        if (l < 0)
        {
            LOG(Level::FATAL) << "listen error";
            exit(3);
        }
        LOG(Level::DEBUG) << "listen success";
    }

    class ThreadData
    {
    public:
        ThreadData(int fd, TcpServer *tsvr, InetAddr addr)
            : _fd(fd), _tsvr(tsvr), _addr(addr)
        {
        }
        int _fd;
        TcpServer *_tsvr;
        InetAddr _addr;
    };
    static void *Routinue(void *argv)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(argv);
        td->_tsvr->Server(td->_fd, td->_addr);
        return nullptr;
    }
    void Start()
    {
        while (true)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            bzero(&peer, len);
            int rwfd = accept(_sockfd, (struct sockaddr *)&peer, &len);
            if (rwfd < 0)
            {
                LOG(Level::FATAL) << "accept error";
                exit(4);
            }
            LOG(Level::DEBUG) << "accept success";
            // 多线程
            pthread_t tid;

            ThreadData *td = new ThreadData(rwfd, this, peer);
            pthread_create(&tid, nullptr, Routinue, td);
        }
    }

private:
    int _sockfd;
    uint16_t _port;
    func_t _func;
};

// class TcpServer
// {
//     void Server(int rwfd)
//     {
//         while (true)
//         {
//             char buff[256];
//             int rn = read(rwfd, buff, sizeof(buff) - 1);
//             if (rn < 0)
//             {
//                 // read出错
//                 LOG(Level::ERROR) << "read error";
//                 break;
//             }
//             else if (rn == 0)
//             {
//                 // write端退出
//                 LOG(Level::INFO) << "writer is exit";
//                 break;
//             }
//             // 读取成功
//             buff[rn] = '\0';
//             std::cout << "read : " << buff << std::endl;
//             // 发送信息, 这里简单将信息发送回去
//             int wn = write(rwfd, buff, rn);
//             if (wn < 0)
//             {
//                 LOG(Level::ERROR) << "write error";
//                 break;
//             }
//         }
//     }
//     void Server(int rwfd, InetAddr &addr)
//     {
//         while (true)
//         {
//             char buff[256];
//             int rn = read(rwfd, buff, sizeof(buff) - 1);
//             if (rn < 0)
//             {
//                 // read出错
//                 LOG(Level::ERROR) << "read error";
//                 break;
//             }
//             else if (rn == 0)
//             {
//                 // write端退出
//                 LOG(Level::INFO) << "writer is exit";
//                 break;
//             }
//             // 读取成功
//             buff[rn] = '\0';
//             std::cout << addr.ToString() << " : " << buff << std::endl;
//             // 发送信息, 这里简单将信息发送回去
//             int wn = write(rwfd, buff, rn);
//             if (wn < 0)
//             {
//                 LOG(Level::ERROR) << "write error";
//                 break;
//             }
//         }
//     }

// public:
//     TcpServer(uint16_t port) : _sockfd(-1), _port(port)
//     {
//     }
//     ~TcpServer() {}
//     void Init()
//     {
//         // 1. socket
//         _sockfd = socket(AF_INET, SOCK_STREAM, 0);
//         if (_sockfd < 0)
//         {
//             LOG(Level::FATAL) << "socket error";
//             exit(1);
//         }
//         LOG(Level::DEBUG) << "socket success";
//         // 2. bind
//         InetAddr addr(_port);
//         int b = bind(_sockfd, addr.GetInetAddr(), addr.GetLen());
//         if (b < 0)
//         {
//             LOG(Level::FATAL) << "bind error";
//             exit(2);
//         }
//         LOG(Level::DEBUG) << "bind success";
//         int l = listen(_sockfd, 5);
//         if (l < 0)
//         {
//             LOG(Level::FATAL) << "listen error";
//             exit(3);
//         }
//         LOG(Level::DEBUG) << "listen success";
//     }

//     class ThreadData
//     {
//     public:
//         ThreadData(int fd, TcpServer *tsvr, InetAddr addr)
//             : _fd(fd), _tsvr(tsvr), _addr(addr)
//         {
//         }
//         int _fd;
//         TcpServer *_tsvr;
//         InetAddr _addr;
//     };
//     static void *Routinue(void *argv)
//     {
//         pthread_detach(pthread_self());
//         ThreadData *td = static_cast<ThreadData *>(argv);
//         td->_tsvr->Server(td->_fd, td->_addr);
//         return nullptr;
//     }
//     void Start()
//     {
//         while (true)
//         {
//             struct sockaddr_in peer;
//             socklen_t len = sizeof(peer);
//             bzero(&peer, len);
//             int rwfd = accept(_sockfd, (struct sockaddr *)&peer, &len);
//             if (rwfd < 0)
//             {
//                 LOG(Level::FATAL) << "accept error";
//                 exit(4);
//             }
//             LOG(Level::DEBUG) << "accept success";
//             // 读写
//             // Server(rwfd);

//             // // 多进程
//             // pid_t pid = fork();
//             // if (pid < 0)
//             // {
//             //     LOG(Level::FATAL) << "fork error";
//             //     exit(1);
//             // }
//             // else if (pid == 0)
//             // {
//             //     close(_sockfd);
//             //     if (fork() == 0)
//             //         Server(rwfd);
//             //     exit(0);
//             // }
//             // // 父进程
//             // waitpid(pid, nullptr, 0);

//             // 多线程
//             pthread_t tid;

//             ThreadData *td = new ThreadData(rwfd, this, peer);
//             pthread_create(&tid, nullptr, Routinue, td);
//         }
//     }

// private:
//     int _sockfd;
//     uint16_t _port;
// };